package ihm.views.main;

import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.LayoutManager;

import ihm.controllers.ATKcontroller;
import ihm.models.ATKlistener;
import ihm.models.events.CharacterChangedEvent;
import ihm.models.events.EquipmentChangedEvent;
import ihm.models.events.ItemTypeChangedEvent;
import ihm.models.events.LanguageChangedEvent;
import ihm.models.events.QueryChangedEvent;
import ihm.models.events.StatChangedEvent;

import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSeparator;

import characters.Characters;
import characters.Statistics;

import systems.languages.MultiLanguages;

public class StatisticsPanel extends JPanel implements ATKlistener{

  private static final long serialVersionUID = 1L;

  private static JLabel statisticTitle = new JLabel("<html><h1>"+MultiLanguages.getProperties("stat.Title.label")+"</h1></html>");
  private static JLabel hpLabel = new JLabel();
  private static JLabel mpLabel= new JLabel();
  private static JLabel powerLabel= new JLabel();
  private static JLabel healthLabel= new JLabel();
  private static JLabel agilityLabel= new JLabel();
  private static JLabel accLabel= new JLabel();
  private static JLabel knowLabel= new JLabel();
  private static JLabel willLabel= new JLabel();
  private static JLabel phyDefLabel= new JLabel();
  private static JLabel evasionLabel= new JLabel();
  private static JLabel blockLabel= new JLabel();
  private static JLabel parryLabel= new JLabel();
  //MagicalRes
  private static JLabel magicResLabel= new JLabel();
  private static JLabel fireResLabel= new JLabel();
  private static JLabel windResLabel= new JLabel();
  private static JLabel waterResLabel= new JLabel();
  private static JLabel earthResLabel= new JLabel();
  //Main hand
  private static JLabel mainHandLabel= new JLabel();
  private static JLabel mainHandAccLabel= new JLabel();
  private static JLabel mainHandAtkLabel= new JLabel();
  private static JLabel mainHandCritRateLabel= new JLabel();

  //Off hand
  private static JLabel offHandLabel= new JLabel();
  private static JLabel offHandAccLabel= new JLabel();
  private static JLabel offHandAtkLabel= new JLabel();
  private static JLabel offHandCritRateLabel= new JLabel();

  private static JLabel atkSpeedLabel= new JLabel();
  private static JLabel speedLabel= new JLabel();
  private static JLabel magicBoostLabel= new JLabel();
  private static JLabel magicAccLabel= new JLabel();

  private static ATKcontroller controller;
  private static Statistics stat;
  private static Characters character;
  //Panel stuff
  private static LayoutManager gridBagLayout = new GridBagLayout();
  private static GridBagConstraints  gbc = new GridBagConstraints();

  public StatisticsPanel(ATKcontroller controller)
  {
    super();
    
    StatisticsPanel.controller = controller;
    StatisticsPanel.character = controller.getModel().getCharacter();
    StatisticsPanel.stat = character.getStat();

    this.setLayout(gridBagLayout); 
    
    this.setBackground(Color.white);
    this.setBorder(BorderFactory.createLineBorder(Color.gray));

    this.updateLabels();
    
    this.buildPanel();
    
  }

  public void updateLabels()
  {
    String boldStart = "<html><b>";
    String boldEnd = "</b></html>";

    statisticTitle.setText("<html><h1>"+MultiLanguages.getProperties("stat.Title.label")+"</h1></html>");
    hpLabel.setText(boldStart+MultiLanguages.getProperties("stat.HP.label")+boldEnd);
    mpLabel.setText(boldStart+MultiLanguages.getProperties("stat.MP.label")+boldEnd);
    powerLabel.setText(boldStart+MultiLanguages.getProperties("stat.Power.label")+boldEnd);
    healthLabel.setText(boldStart+MultiLanguages.getProperties("stat.Health.label")+boldEnd);
    agilityLabel.setText(boldStart+MultiLanguages.getProperties("stat.Agility.label")+boldEnd);
    accLabel.setText(boldStart+MultiLanguages.getProperties("stat.Accuracy.label")+boldEnd);
    knowLabel.setText(boldStart+MultiLanguages.getProperties("stat.Knowledge.label")+boldEnd);
    willLabel.setText(boldStart+MultiLanguages.getProperties("stat.Will.label")+boldEnd);
    phyDefLabel.setText(boldStart+MultiLanguages.getProperties("stat.PhyDef.label")+boldEnd);
    evasionLabel.setText(boldStart+MultiLanguages.getProperties("stat.Evasion.label")+boldEnd);
    blockLabel.setText(boldStart+MultiLanguages.getProperties("stat.Block.label")+boldEnd);
    parryLabel.setText(boldStart+MultiLanguages.getProperties("stat.Parry.label")+boldEnd);
    //MagicalRes
    magicResLabel.setText(boldStart+MultiLanguages.getProperties("stat.MagicRes.label")+boldEnd);
    fireResLabel.setText(boldStart+MultiLanguages.getProperties("stat.FireRes.label")+boldEnd);
    windResLabel.setText(boldStart+MultiLanguages.getProperties("stat.WindRes.label")+boldEnd);
    waterResLabel.setText(boldStart+MultiLanguages.getProperties("stat.WaterRes.label")+boldEnd);
    earthResLabel.setText(boldStart+MultiLanguages.getProperties("stat.EarthRes.label")+boldEnd);
    //Main hand
    mainHandLabel.setText(boldStart+MultiLanguages.getProperties("equipment.MainHand.label")+boldEnd);
    mainHandAccLabel.setText(boldStart+MultiLanguages.getProperties("stat.Accuracy.label")+boldEnd);
    mainHandAtkLabel.setText(boldStart+MultiLanguages.getProperties("stat.Attack.label")+boldEnd);
    mainHandCritRateLabel.setText(boldStart+MultiLanguages.getProperties("stat.CriticRate.label")+boldEnd);
    //Off hand
    offHandLabel.setText(boldStart+MultiLanguages.getProperties("equipment.OffHand.label")+boldEnd);
    offHandAccLabel.setText(boldStart+MultiLanguages.getProperties("stat.Accuracy.label")+boldEnd);
    offHandAtkLabel.setText(boldStart+MultiLanguages.getProperties("stat.Attack.label")+boldEnd);
    offHandCritRateLabel.setText(boldStart+MultiLanguages.getProperties("stat.CriticRate.label")+boldEnd);

    atkSpeedLabel.setText(boldStart+MultiLanguages.getProperties("stat.AtkSpeed.label")+boldEnd);
    speedLabel.setText(boldStart+MultiLanguages.getProperties("stat.Speed.label")+boldEnd);
    magicBoostLabel.setText(boldStart+MultiLanguages.getProperties("stat.MagicBoost.label")+boldEnd);
    magicAccLabel.setText(boldStart+MultiLanguages.getProperties("stat.MagicAcc.label")+boldEnd);
  }

  private void buildPanel()
  {
    this.buildTitle();
    //BasicStat
    buildBasicStat();
    //Jsep
    this.buildJSeparator(0, 9, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, 2, 1);
    //Phy Def Stat
    this.buildPhyDefStat();
    //Jsep
    this.buildJSeparator(0, 14, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, 2, 1);
    //Magical Stat
    this.buildMagDef();
    //Vertival Separator
    gbc.gridx=2;
    gbc.gridy=1;
    gbc.anchor=GridBagConstraints.CENTER;
    gbc.fill=GridBagConstraints.VERTICAL;
    gbc.gridheight=GridBagConstraints.REMAINDER;
    gbc.gridwidth=1;
    this.add(new JSeparator(JSeparator.VERTICAL), gbc);
    this.buildJSeparator(2, 1, GridBagConstraints.CENTER, GridBagConstraints.VERTICAL, 1, 19);
    //MainHandStat
    this.buildMainHand();
    //JSep
    this.buildJSeparator(3, 5, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, 2, 1);
    //Off hand
    this.buildOffHand();
    //JSep
    this.buildJSeparator(3, 10, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, 2, 1);
    //Magic Stat
    this.buildMagicStat();
    //JSep
    this.buildJSeparator(3, 13, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, 2, 1);
    //Speed Stat
    this.buildSpeedStat();
  }
  private void buildTitle()
  {
    gbc.gridx = 0;
    gbc.gridy = 0;
    gbc.gridheight = 1; //Occupera 1 ligne verticalements
    gbc.gridwidth = GridBagConstraints.REMAINDER;//Dernier element sur la ligne
    gbc.anchor = GridBagConstraints.CENTER;
    //ajout au panel
    this.add(statisticTitle, gbc);

  }

  private void buildBasicStat()
  {
    int gridx = 0;
    int gridy = 1;
    //----HP
    this.buildStatLine(gridx, gridy,hpLabel,
        constructJLabel(stat.getTotalHp(), character.getBonusHp(), character.getMaxHp()));
    gridy++;
    //----MP
    this.buildStatLine(gridx, gridy, mpLabel, 
        constructJLabel(stat.getTotalMp(), character.getBonusMp(), character.getMaxMp()));
    gridy++;
    //----Power
    this.buildStatLine(gridx, gridy, powerLabel,
        constructJLabel(character.getPower(), 0, 0));
    gridy++;
    //----Health
    this.buildStatLine(gridx, gridy, healthLabel, 
        constructJLabel(character.getHealth(), 0, 0));
    gridy++;
    //----Agility
    this.buildStatLine(gridx, gridy, agilityLabel,
        constructJLabel(character.getAgility(), 0, 0));
    gridy++;
    //----Accuracy
    this.buildStatLine(gridx, gridy, accLabel,
        constructJLabel(character.getAccuracy(), 0, 0));
    gridy++;
    //----Know
    this.buildStatLine(gridx, gridy, knowLabel,
        constructJLabel(character.getKnowledge(), 0, 0));
    gridy++;
    //----will
    this.buildStatLine(gridx, gridy, willLabel,
        constructJLabel(character.getWill(), 0, 0));

  }

  private void buildPhyDefStat()
  {
    int gridx = 0;
    int gridy = 10;
    //----PhyDef
    this.buildStatLine(gridx, gridy, phyDefLabel,
        constructJLabel(stat.getTotalPhysicalDef(), character.getBonusPhyDef(), character.getPhysicalDef()));

    gridy++;
    //----Evasion
    this.buildStatLine(gridx, gridy, evasionLabel, 
        constructJLabel(stat.getTotalEvasion(), character.getBonusEvasion(), character.getEvasion()));
    gridy++;
    //----Block
    this.buildStatLine(gridx, gridy, blockLabel,
        constructJLabel(stat.getTotalBlock(), character.getBonusBlock(), character.getBlock()));
    gridy++;
    //----Pary
    this.buildStatLine(gridx, gridy, parryLabel,
        constructJLabel(stat.getTotalParry(), character.getBonusParry(), character.getParry()));
    gridy++;
  }

  private void buildMagDef()
  {
    int gridx = 0;
    int gridy = 15;

    //----Mag Res
    this.buildStatLine(gridx, gridy, magicResLabel,
        constructJLabel(stat.getTotalMagicalResistance(), character.getBonusMagicResist(), character.getMagicalResist()));
    gridy++;
    //----Fire Res
    this.buildStatLine(gridx, gridy, fireResLabel,
        constructJLabel(character.getResistFire(), 0, 0));
    gridy++;
    //----Block
    this.buildStatLine(gridx, gridy, windResLabel,
        constructJLabel(character.getResistWind(), 0, 0));
    gridy++;
    //----Pary
    this.buildStatLine(gridx, gridy, earthResLabel,
        constructJLabel(character.getResistEarth(), 0, 0));
    gridy++;
    //----Water
    this.buildStatLine(gridx, gridy, waterResLabel,
        constructJLabel(character.getResistWater(), 0, 0));
  }

  private void buildStatLine(int gridx, int gridy, JLabel name, JLabel value) 
  {
    //Build Stat's name
    gbc.gridx = gridx;
    gbc.gridy = gridy;
    gbc.gridheight = 1; //Occupera 1 ligne verticalements
    gbc.gridwidth = 1;//Dernier element sur la ligne
    gbc.anchor = GridBagConstraints.LINE_START;
    //ajout au panel
    this.add(name, gbc);  
    //Build Stat's Value
    gbc.gridx = gridx+1;
    gbc.anchor = GridBagConstraints.LINE_END;
    gbc.fill = GridBagConstraints.NONE;
    //ajout au panel
    this.add(value, gbc);  
  }

  private void buildMainHand()
  {
    int gridx = 3;
    int gridy = 1;
    //--Title
    gbc.gridx = gridx;
    gbc.gridy = gridy;
    gbc.anchor = GridBagConstraints.CENTER;
    gbc.gridwidth = GridBagConstraints.REMAINDER;
    gbc.gridheight = 1;
    this.add(mainHandLabel, gbc);
    gridy++;
    //----Atk
    this.buildStatLine(gridx, gridy, mainHandAtkLabel,
        constructJLabel(stat.getTotalMainHandAttack(), character.getBonusMainHandAttack(), character.getMainHandAttack()));
    gridy++;
    //----Accu
    this.buildStatLine(gridx, gridy, mainHandAccLabel,
        constructJLabel(stat.getTotalMainHandAccuracy(), character.getBonusMainHandAccuracy(), character.getMainHandAccuracy()));
    gridy++;
    //----Crit
    this.buildStatLine(gridx, gridy, mainHandCritRateLabel,
        constructJLabel(stat.getTotalMainHandCritRate(), character.getBonusMainHandCritRate(), character.getMainHandCritRate()));
  }

  private void buildOffHand()
  {
    int gridx = 3;
    int gridy = 6;
    //--Title
    gbc.gridx = gridx;
    gbc.gridy = gridy;
    gbc.anchor = GridBagConstraints.CENTER;
    gbc.gridwidth = GridBagConstraints.REMAINDER;
    gbc.gridheight = 1;
    this.add(offHandLabel, gbc);
    gridy++;
    //----Atk
    this.buildStatLine(gridx, gridy, offHandAtkLabel,
        constructJLabel(stat.getTotalOffHandAttack(), character.getBonusOffHandAttack(), character.getOffHandAttack()));
    gridy++;
    //----Accu
    this.buildStatLine(gridx, gridy, offHandAccLabel,
        constructJLabel(stat.getTotalOffHandAccuracy(), character.getBonusOffHandAccuracy(), character.getOffHandAccuracy()));
    gridy++;
    //----Crit
    this.buildStatLine(gridx, gridy, offHandCritRateLabel,
        constructJLabel(stat.getTotaloffHandCritRate(), character.getBonusOffHandCritRate(), character.getoffHandCritRate()));
  }

  private void buildMagicStat()
  {
    int gridx = 3;
    int gridy = 11;
    //----Magic Boost
    this.buildStatLine(gridx, gridy, magicBoostLabel,
        constructJLabel(stat.getTotalMagicPower(), character.getBonusMagicPower(), character.getMagicPower()));
    gridy++;
    //----Magic Acc
    this.buildStatLine(gridx, gridy, magicAccLabel,
        constructJLabel(stat.getTotalMagicAccuracy(), character.getBonusMagicAccuracy(), character.getMagicAccuracy()));
  }
  
  private void buildSpeedStat()
  {
    int gridx = 3;
    int gridy = 14;
    //----Attack Speed
    this.buildStatLine(gridx, gridy, atkSpeedLabel,
        constructJLabel(stat.getTotalAttackSpeed(), character.getBonusAttackSpeed(), character.getAttackSpeed()));
    gridy++;
    //----Speed
    this.buildStatLine(gridx, gridy, speedLabel,
        constructJLabel(character.getRunSpeed(), 0, 0));
  }
  private void buildJSeparator(int gridx, int gridy, int anchor, int fill, int width, int height)
  {
    gbc.gridx = gridx;
    gbc.gridy = gridy;
    gbc.gridwidth = width;
    gbc.gridheight = height;
    //Point d'ancrage � l'interieur des cellules
    gbc.anchor = anchor;
    gbc.fill = fill;
    //Ajout au panel
    this.add(new JSeparator(), gbc);
  }

  private JLabel constructJLabel(int totalValue, int bonusValue, int normalValue)
  {
    JLabel tmp = new JLabel(String.valueOf(totalValue));
    if(bonusValue > 0)
    {
      tmp.setForeground(Color.green);
      tmp.setToolTipText(normalValue+" + ("+bonusValue+")");
    }
    else if(bonusValue < 0)
    {
      tmp.setForeground(Color.red);
      tmp.setToolTipText(normalValue+" - ("+bonusValue+")");
    }
    return tmp;
  }
  
  private JLabel constructJLabel(double totalValue, double bonusValue, double normalValue)
  {
    JLabel tmp = new JLabel(String.valueOf(totalValue));
    if(bonusValue > 0)
    {
      tmp.setForeground(Color.green);
      tmp.setToolTipText(normalValue+" + ("+bonusValue+")");
    }
    else if(bonusValue < 0)
    {
      tmp.setForeground(Color.red);
      tmp.setToolTipText(normalValue+" - ("+bonusValue+")");
    }
    return tmp;
  }

  @Override
  public void EquipmentChanged(EquipmentChangedEvent event)
  {
    
  }

  @Override
  public void ItemTypeChanged(ItemTypeChangedEvent event) {
    //Nothing here
  }

  @Override
  public void LanguageChanged(LanguageChangedEvent event) {
    updateLabels();
  }

  @Override
  public void QueryChanged(QueryChangedEvent event) {
    //nothing here
  }

  @Override
  public void StatChanged(StatChangedEvent event) {
    stat = event.getNewStatistics();
    this.removeAll();
    this.buildPanel();
    this.repaint();
    this.validate();
  }

  @Override
  public void CharacterChanged(CharacterChangedEvent event) {
    StatisticsPanel.character = event.getNewCharacter();
    this.StatChanged(new StatChangedEvent(this, StatisticsPanel.character.getStat()));
  }
}
